/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// [Start header_file]
#include "napi/native_api.h"
#include "network/netmanager/net_connection.h"
#include "network/netmanager/net_connection_type.h"
// [End header_file]
#include <cstring>
 
const size_t MIN_ARG_COUNT = 3; // 最小参数个数，用于函数参数检查
const int PARAMETER_ERROR_CODE = 401; // 错误代码，表示参数错误
const size_t MAX_HOST_LENGTH = 256; // 用于存储 host 的最大长度
const size_t MAX_SERV_LENGTH = 256; // 用于存储 serv 的最大长度
const size_t NET_ID_ARG_INDEX = 2;  // 代表 netId 的索引位置，表示接收到的第三个参数
const size_t HOST_ARG_INDEX = 0;     // args 数组中的索引，表示 host 参数的位置
const size_t SERV_ARG_INDEX = 1;     // args 数组中的索引，表示 serv 参数的位置
const int SUCCESS_CODE = 0;  // 表示成功的状态码
 
// 封装错误结果生成函数
napi_value CreateErrorResult(napi_env env, int32_t errorCode)
{
    napi_value result;
    napi_create_int32(env, errorCode, &result);
    return result;
}
 
// [Start build_project1]
// 获取默认网络的函数
static napi_value GetDefaultNet(napi_env env, napi_callback_info info)
{
    size_t argc = 1; // 期望接收一个函数
    napi_value args[1] = {nullptr}; // 存储接收到的参数
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    // [StartExclude build_project1]
    if (argc < 1) { // 如果参数小于1
        return CreateErrorResult(env, PARAMETER_ERROR_CODE);
    }

    int32_t param;
    napi_get_value_int32(env, args[0], &param); // 从 args[0] 获取整数值并存储到 param 中
    // [EndExclude build_project1]
    NetConn_NetHandle netHandle;
    if (param == 0) { // 如果参数是0
        param = OH_NetConn_GetDefaultNet(NULL);
    } else {
        param = OH_NetConn_GetDefaultNet(&netHandle);
    }

    napi_value result;
    napi_create_int32(env, param, &result);
    return result;
}

// 获取默认网络ID的函数
static napi_value NetId(napi_env env, napi_callback_info info)
{
    int32_t defaultNetId;
    NetConn_NetHandle netHandle;
    OH_NetConn_GetDefaultNet(&netHandle);
    defaultNetId = netHandle.netId; // 获取默认的 netId
    napi_value result;
    napi_create_int32(env, defaultNetId, &result);
    return result;
}
// [End build_project1]

// 检查默认网络是否激活的函数
static napi_value HasDefaultNet(napi_env env, napi_callback_info info)
{
    int32_t hasDefaultNet = 0;
    int32_t result = OH_NetConn_HasDefaultNet(&hasDefaultNet); // 使用引用传递 hasDefaultNet
    napi_value napiResult;
    if (result == 0) {
        napi_create_int32(env, hasDefaultNet, &napiResult); // 激活为 1，未激活为 0
    } else {
        napi_create_int32(env, result, &napiResult); // 返回错误码
    }

    return napiResult;
}
 
// 检查默认网络的流量是否受限
static napi_value IsDefaultNetMetered(napi_env env, napi_callback_info info)
{
    int32_t isMetered = 0;
    int32_t result = OH_NetConn_IsDefaultNetMetered(&isMetered);
    napi_value napiResult;
    if (result == 0) {
        napi_create_int32(env, isMetered, &napiResult); // 如果受限返回 1，未受限返回 0
    } else {
        napi_create_int32(env, result, &napiResult); // 返回错误码
    }

    return napiResult;
}
 
// 获取指定网络连接属性的函数
static napi_value GetConnectionProperties(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_status status;
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    if (status != napi_ok || argc < 1) {
        return CreateErrorResult(env, PARAMETER_ERROR_CODE); // 参数错误
    }

    NetConn_NetHandle netHandle;
    napi_get_value_int32(env, args[0], &netHandle.netId);
    NetConn_ConnectionProperties connProps;
    int32_t statusCode = OH_NetConn_GetConnectionProperties(&netHandle, &connProps);
    if (statusCode == SUCCESS_CODE) {
        napi_create_int32(env, 0, &result);
    } else {
        napi_create_int32(env, statusCode, &result); // 返回错误码
    }
 
    return result;
}
 
// 获取网络能力的函数
static napi_value GetNetCapabilities(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_status status;
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    if (status != napi_ok || argc < 1) {
        return CreateErrorResult(env, PARAMETER_ERROR_CODE); // 参数错误
    }
 
    NetConn_NetHandle netHandle;
    napi_get_value_int32(env, args[0], &netHandle.netId);
    NetConn_NetCapabilities netCapabilities;
    int32_t statusCode = OH_NetConn_GetNetCapabilities(&netHandle, &netCapabilities);
    if (statusCode == SUCCESS_CODE) {
        napi_create_int32(env, 0, &result); // 成功
    } else {
        napi_create_int32(env, statusCode, &result); // 返回错误码
    }
 
    return result;
}
 
// 获取默认 HTTP 代理配置的函数
static napi_value GetDefaultHttpProxy(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_status status;
    NetConn_HttpProxy httpProxy = {};
    int32_t statusCode = OH_NetConn_GetDefaultHttpProxy(&httpProxy);
    if (statusCode == SUCCESS_CODE) {
        napi_create_int32(env, 0, &result); // 成功
    } else {
        napi_create_int32(env, statusCode, &result); // 返回错误码
    }
 
    return result;
}
 
// 获取 DNS 信息的函数
static napi_value GetAddrInfo(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_status status;
    size_t argc = MIN_ARG_COUNT; // 期望接收 3 个参数
    napi_value args[MIN_ARG_COUNT] = {nullptr}; // 存储接收到的参数
    status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    if (status != napi_ok || argc < MIN_ARG_COUNT) {
        return CreateErrorResult(env, PARAMETER_ERROR_CODE); // 参数错误
    }
 
    char host[MAX_HOST_LENGTH];
    char serv[MAX_SERV_LENGTH];
    int32_t netId;
    struct addrinfo hint;
    struct addrinfo *res = nullptr;
    napi_get_value_string_utf8(env, args[HOST_ARG_INDEX], host, sizeof(host), nullptr);
    napi_get_value_string_utf8(env, args[SERV_ARG_INDEX], serv, sizeof(serv), nullptr);
    napi_get_value_int32(env, args[NET_ID_ARG_INDEX], &netId);
    memset(&hint, 0, sizeof(hint));
    int32_t statusCode = OH_NetConn_GetAddrInfo(host, serv, &hint, &res, netId);
    if (statusCode == SUCCESS_CODE) {
        napi_create_int32(env, SUCCESS_CODE, &result); // 成功
        struct addrinfo *cur = res;
        while (cur != nullptr) {
            cur = cur->ai_next;
        }
        OH_NetConn_FreeDnsResult(res); // 释放内存
    } else {
        return CreateErrorResult(env, statusCode); // 错误：返回错误码
    }
 
    return result;
}
 
// 获取所有活动的网络句柄的函数
static napi_value GetAllNets(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_status status;
    NetConn_NetHandleList netHandleList;
    memset(&netHandleList, 0, sizeof(netHandleList));
    int32_t statusCode = OH_NetConn_GetAllNets(&netHandleList);
    if (statusCode == SUCCESS_CODE) {
        napi_create_int32(env, 0, &result); // 成功
    } else {
        napi_create_int32(env, statusCode, &result); // 返回错误码
    }

    return result;
}
 
 
// 自定义 DNS 解析器的函数
int MyCustomDnsResolver(const char *host, const char *serv, const struct addrinfo *hint, struct addrinfo **res)
{
    struct addrinfo hints;
    struct addrinfo *result;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    int err = getaddrinfo(host, serv, &hints, &result);
    if (err != 0) {
        return -1;
    }
 
    *res = result;
    return 0;
}
 
// 注册自定义 DNS 解析器的函数
static napi_value RegisterDnsResolver(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_status status;
    int statusCode = OH_NetConn_RegisterDnsResolver(MyCustomDnsResolver);
    if (statusCode == SUCCESS_CODE) {
        napi_create_int32(env, 0, &result);
    } else {
        napi_create_int32(env, statusCode, &result);
    }
 
    return result;
}
 
// 注销自定义 DNS 解析器的函数
static napi_value UnregisterDnsResolver(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_status status;
    int32_t statusCode = OH_NetConn_UnregisterDnsResolver();
    if (statusCode == SUCCESS_CODE) {
        napi_create_int32(env, 0, &result);
    } else {
        napi_create_int32(env, statusCode, &result);
    }

    return result;
}
 
// [Start build_project2]
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
    napi_property_descriptor desc[] = {
        {"GetDefaultNet", nullptr, GetDefaultNet, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"NetId", nullptr, NetId, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"HasDefaultNet", nullptr, HasDefaultNet, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"IsDefaultNetMetered", nullptr, IsDefaultNetMetered, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"GetConnectionProperties", nullptr, GetConnectionProperties, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"GetNetCapabilities", nullptr, GetNetCapabilities, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"GetDefaultHttpProxy", nullptr, GetDefaultHttpProxy, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"GetAddrInfo", nullptr, GetAddrInfo, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"GetAllNets", nullptr, GetAllNets, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"RegisterDnsResolver", nullptr, RegisterDnsResolver, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"UnregisterDnsResolver", nullptr, UnregisterDnsResolver, nullptr, nullptr, nullptr, napi_default, nullptr}};
        
    constexpr size_t desc_size = 11; // 定义描述符数组的大小，表示有 11 个属性描述符
    napi_define_properties(env, exports, desc_size, desc);
    return exports;
}
EXTERN_C_END
// [End build_project2]

// [Start build_project3] 
static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "entry",
    .nm_priv = ((void *)0),
    .reserved = {0},
};
 
extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
// [End build_project3]